# -*- coding: utf-8 -*-
# created on 2016/10/14


from mathsolver.functions.base import *
from mathsolver.functions.yuan.property import ErYuanErCiCoeff
from sympy.abc import x, y, p
from sympy import sqrt, Abs, pi


# 将椭圆化为标准型
class OvalNormalized(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        panbieshi = d ** 2 / (4 * a) + e ** 2 / (4 * b) - f
        biaozhunshi = (x + d / (2 * a)) ** 2 / (panbieshi / a) + (y + e / (2 * b)) ** 2 / (panbieshi / b)
        self.steps.append(["", "椭圆的标准方程为%s" % (BaseEq([biaozhunshi, 1]).printing())])
        self.output.append(BaseEq([biaozhunshi, 1]))
        self.label.add("将椭圆化为标准型")
        return self


# 求椭圆x,y的系数
class OvalCoeffs(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        panbieshi = d ** 2 / (4 * a) + e ** 2 / (4 * b) - f
        x_coeff = panbieshi / a
        y_coeff = panbieshi / b
        self.output.append(BaseValues([x_coeff, y_coeff]))
        return self


# 求椭圆的对称中心
class OvalSymmetryPoint(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        point = [-d / (2 * a), -e / (2 * b)]
        # self.steps.append(["", "∴椭圆的中心为%s" % (BasePoint({"name": "", "value": point}).printing())])
        self.output.append(BasePoint({"name": "", "value": point}))
        return self


# 求椭圆方程的a, b, c
class OvalAbc(BaseFunction):
    def solver(self, *args):
        x_coeff, y_coeff = args[0].sympify()
        if str(x_coeff) == "a**2" and str(y_coeff) == "b**2":
            self.output.append(BaseValues([Symbol("a"), Symbol("b"), sqrt(x_coeff - y_coeff)]))
        elif (not x_coeff.free_symbols) and (not y_coeff.free_symbols):
            a = sqrt(max(x_coeff, y_coeff))
            b = sqrt(min(x_coeff, y_coeff))
            c = sqrt(a ** 2 - b ** 2)
            self.steps.append(
                ["", "∴椭圆的长半轴为%s, 短半轴为%s, 焦半径为%s" % (new_latex(a), new_latex(b), new_latex(c))])
            self.output.append(BaseValues([a, b, c]))
            self.label.add("求椭圆的a,b,c")
        else:
            f = (x_coeff - y_coeff).expand().simplify()
            symbol = list(f.free_symbols)
            if len(symbol) == 0:
                if f > 0:
                    self.output.append(BaseValues([sqrt(x_coeff), sqrt(y_coeff), sqrt(f)]))
                else:
                    self.output.append(BaseValues([sqrt(y_coeff), sqrt(x_coeff), sqrt(-f)]))
            else:
                self.output.append(BaseValues([sqrt(x_coeff), sqrt(y_coeff), sqrt(f)]))
                # x_answer = solveset(x_coeff > 0, symbol[0], S.Reals)
                # y_answer = solveset(y_coeff > 0, symbol[0], S.Reals)
                # jie1 = solveset(x_coeff - y_coeff > 0, symbol[0], S.Reals)
                # answer1 = x_answer & y_answer & jie1
                # a1 = sqrt(x_coeff)
                # b1 = sqrt(y_coeff)
                # c1 = sqrt(a1**2 - b1**2)
                # jie2 = solveset(x_coeff - y_coeff < 0, symbol[0], S.Reals)
                # answer2 = x_answer & y_answer & jie2
                # a2 = sqrt(y_coeff)
                # b2 = sqrt(x_coeff)
                # c2 = sqrt(a2 ** 2 - b2 ** 2)
                # self.steps.append(["", "当%s∈%s时，" %(latex(symbol[0]), latex(answer1))])
                # self.steps.append(["", "∴椭圆的长半轴为%s, 短半轴为%s, 焦半径为%s" % (latex(a1), latex(b1), latex(c1))])
                # self.steps.append(["", "当%s∈%s时，" % (latex(symbol[0]), latex(answer2))])
                # self.steps.append(["", "∴椭圆的长半轴为%s, 短半轴为%s, 焦半径为%s" % (latex(a2), latex(b2), latex(c2))])
                # self.output.append([[symbol[0], answer1, a1, b1, c1],[symbol[0], answer2, a2, b2, c2]])
                self.label.add("求含参数的椭圆的a,b,c")
        return self


# 求椭圆方程的a, b, c
class SimpleOvalAbc(BaseFunction):
    def solver(self, *args):
        x_coeff, y_coeff = args[0].sympify()
        a = sqrt(max(x_coeff, y_coeff))
        print(a)
        return self


# 求椭圆的焦距
class OvalJiaoJu(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BaseValues):
            a, b, c = args[0].sympify()
            jiaoju = 2 * c
            self.steps.append(["", "∴椭圆的焦距为%s" % (new_latex(jiaoju))])
            self.output.append(BaseValue(jiaoju))
        else:
            jiaojulist = []
            for item in args[0]:
                symbol, interval, a, b, c = item
                jiaojulist.append([symbol, interval, 2 * c])
                self.steps.append(["", "当%s∈%s时," % (new_latex(symbol), new_latex(interval))])
                self.steps.append(["", "∴椭圆的焦距为%s" % (new_latex(2 * c))])
            jiaoju = 2 * sqrt(Abs((jiaojulist[0][2] / 2) ** 2))
            self.output.append(BaseValue(jiaoju))
        self.label.add("求椭圆的焦距")
        return self


# 求椭圆的离心率
class OvalEccentricity(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BaseValues):
            a, b, c = args[0].sympify()
            e = c / a
            self.steps.append(["", "∴椭圆的离心率为%s" % (new_latex(e))])
            self.output.append(BasePoly(e))
            self.label.add("求椭圆的离心率")
        else:
            lixinlv = []
            for item in args[0]:
                symbol, interval, a, b, c = item
                lixinlv.append([symbol, interval, c / a])
                self.steps.append(["", "当%s∈%s时," % (new_latex(symbol), new_latex(interval))])
                self.steps.append(["", "椭圆的离心率为%s" % (new_latex(c / a))])
            self.output.append(lixinlv)
        return self


# 求椭圆的面积
class OvalArea(BaseFunction):
    def solver(self, *args):
        a, b, c = args[0].sympify()
        ss = pi * a * b
        self.steps.append(["", "∴椭圆的面积为%s" % (new_latex(ss))])
        self.output.append(BaseValue(ss))
        self.label.add("求椭圆的面积")
        return self


# 求椭圆的焦点坐标
class OvalFocusPoints(BaseFunction):
    def solver(self, *args):
        symmetry_point = args[0].sympify()
        x_coeff, y_coeff = args[1].sympify()
        text = args[2]
        flags = [0, 0, 0]  # flags[0] 左焦点  flags[1] 右焦点 flags[2] 焦点
        if text.find("左") >= 0:
            flags[0] = 1
        elif text.find("右") >= 0:
            flags[1] = 1
        else:
            flags[2] = 1

        if str(x_coeff) == "a**2" and str(y_coeff) == "b**2":
            a = Symbol("a")
            b = Symbol("b")
        else:
            a = sqrt(x_coeff)
            b = sqrt(y_coeff)

        c = sqrt(a ** 2 - b ** 2)
        if flags[0] == 1:
            left_point = [symmetry_point[0] - c, symmetry_point[1]]
            self.steps.append(["", "椭圆的左焦点坐标为%s" % (BasePoint({"name": "", "value": left_point}).printing())])
            self.output.append(BasePoint({"name": "", "value": left_point}))
            self.label.add("求椭圆的焦点")
        elif flags[1] == 1:
            right_point = [symmetry_point[0] + c, symmetry_point[1]]
            self.steps.append(["", "椭圆的右焦点坐标为%s" % (BasePoint({"name": "", "value": right_point}).printing())])
            self.output.append(BasePoint({"name": "", "value": right_point}))
            self.label.add("求椭圆的焦点")
        elif "正" in text:
            c = sqrt(b ** 2 - a ** 2)
            up_point = [symmetry_point[0], symmetry_point[1] + c]
            self.steps.append(["", "椭圆的上焦点坐标为%s" % (BasePoint({"name": "", "value": up_point}).printing())])
            self.output.append(BasePoint({"name": "", "value": up_point}))
            self.label.add("求椭圆的焦点")
        elif "负" in text:
            c = sqrt(b ** 2 - a ** 2)
            down_point = [symmetry_point[0], symmetry_point[1] - c]
            self.steps.append(["", "椭圆的上焦点坐标为%s" % (BasePoint({"name": "", "value": down_point}).printing())])
            self.output.append(BasePoint({"name": "", "value": down_point}))
            self.label.add("求椭圆的焦点")
        elif flags[2] == 1:
            if (a.free_symbols or b.free_symbols) or a > b:
                left_point = [symmetry_point[0] - c, symmetry_point[1]]
                right_point = [symmetry_point[0] + c, symmetry_point[1]]
                self.steps.append(["", "椭圆的左右焦点坐标分别为%s" % (
                    BasePoints([{"name": "", "value": left_point},
                                {"name": "", "value": right_point}]).printing())])
                self.output.append(BasePoints([{"name": "", "value": left_point},
                                               {"name": "", "value": right_point}]))
            else:
                c = sqrt(b ** 2 - a ** 2)
                up_point = [symmetry_point[0], symmetry_point[1] + c]
                down_point = [symmetry_point[0], symmetry_point[1] - c]
                self.steps.append(["", "椭圆的上下焦点坐标分别为%s" % (
                    BasePoints([{"name": "", "value": up_point},
                                {"name": "", "value": down_point}]).printing())])
                self.output.append(BasePoints([{"name": "", "value": up_point},
                                               {"name": "", "value": down_point}]))
            self.label.add("求椭圆的焦点坐标")
        return self


# 求椭圆的顶点坐标
class OvalPeakPoints(BaseFunction):
    def solver(self, *args):
        symmetry_point = args[0].sympify()
        x_coeff, y_coeff = args[1].sympify()
        left_point = [symmetry_point[0] - sqrt(x_coeff), symmetry_point[1]]
        right_point = [symmetry_point[0] + sqrt(x_coeff), symmetry_point[1]]
        up_point = [symmetry_point[0], symmetry_point[1] + sqrt(y_coeff)]
        down_point = [symmetry_point[0], symmetry_point[1] - sqrt(y_coeff)]
        self.steps.append(["", "∴椭圆的左右顶点分别为%s" % (BasePoints([{"name": "", "value": left_point}, {"name": "", "value": right_point}]).printing())])
        self.steps.append(["", "∴椭圆的上下顶点分别为%s" % (BasePoints([{"name": "", "value": up_point}, {"name": "", "value": down_point}]).printing())])
        self.output.append(BasePoints([{"name": "", "value": left_point}, {"name": "", "value": right_point},
                                       {"name": "", "value": up_point}, {"name": "", "value": down_point}]))
        self.label.add("求椭圆的顶点坐标")
        return self


# 求椭圆的准线方程
class OvalDirectris(BaseFunction):
    def solver(self, *args):
        symmetry_point = args[0].sympify()
        x_coeff, y_coeff = args[1].sympify()
        if x_coeff > y_coeff:
            a = sqrt(x_coeff)
            b = sqrt(y_coeff)
            c = sqrt(a ** 2 - b ** 2)
            eq_left = [x, symmetry_point[0] - a ** 2 / c]
            eq_right = [x, symmetry_point[0] + a ** 2 / c]
            self.steps.append(["", "∴椭圆的左右准线分别为%s" % (BaseZhiXian([{"name": "", "value": eq_left}, {"name": "", "value": eq_right}]).printing())])
            self.output.append(BaseZhiXian([{"name": "", "value": eq_left}, {"name": "", "value": eq_right}]))
        else:
            a = sqrt(y_coeff)
            b = sqrt(x_coeff)
            c = sqrt(a ** 2 - b ** 2)
            eq_up = [y, symmetry_point[1] + a ** 2 / c]
            eq_down = [y, symmetry_point[1] - a ** 2 / c]
            self.steps.append(["", "∴椭圆的上下准线分别为%s" % (BaseZhiXian([{"name": "", "value": eq_up}, {"name": "", "value": eq_down}]).printing())])
            self.output.append(BaseZhiXian([{"name": "", "value": eq_up}, {"name": "", "value": eq_down}]))
        self.label.add("求椭圆的准线方程")
        return self


# 求椭圆的对称轴
class OvalSymmetryAxis(BaseFunction):
    def solver(self, *args):
        symmetry_point = OvalSymmetryPoint().solver(args[0]).output[0].sympify()
        self.steps.append(["", "∴椭圆的对称轴分别为%s" % (BaseZhiXians([{"name": "", "value": [x, symmetry_point[0]]}, {"name": "", "value": [y, symmetry_point[1]]}]).printing())])
        self.output.append(BaseZhiXians([{"name": "", "value": [x, symmetry_point[0]]},
                                         {"name": "", "value": [y, symmetry_point[1]]}]))
        self.label.add("求椭圆的对称轴")
        return self


# 将双曲线化为标准型
class HyperbolaNormalized(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        panbieshi = d ** 2 / (4 * a) + e ** 2 / (4 * b) - f
        biaozhunshi = (x + d / (2 * a)) ** 2 / (panbieshi / a) + (y + e / (2 * b)) ** 2 / (panbieshi / b)
        self.steps.append(["", "双曲线的标准方程为%s" % (BaseEq([biaozhunshi, 1]).printing())])
        self.output.append(BaseValue([biaozhunshi, 1]))
        self.label.add("将双曲线化为标准型")
        return self


# 求双曲线的对称中心
class HyperbolaSymmetryPoint(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        point = [-d / (2 * a), -e / (2 * b)]
        self.steps.append(["", "∴双曲线的中心为%s" % (BasePoint({"name": "", "value": point}).printing())])
        self.output.append(BasePoint({"name": "", "value": point}))
        return self


# 求双曲线的对称轴
class HyperbolaSymmetryAxis(BaseFunction):
    def solver(self, *args):
        symmetry_point = HyperbolaSymmetryPoint().solver(args[0]).output[0].sympify()
        self.steps.append(["", "∴双曲线的对称轴分别为%s" % (BaseZhiXians([{"name": "", "value": [x, symmetry_point[0]]}, {"name": "", "value": [y, symmetry_point[1]]}]).printing())])
        self.output.append(BaseZhiXians([{"name": "", "value": [x, symmetry_point[0]]},
                                         {"name": "", "value": [y, symmetry_point[1]]}]))
        self.label.add("求双曲线的对称轴")
        return self


# 求双曲线x,y的系数
class HyperbolaCoeffs(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        panbieshi = d ** 2 / (4 * a) + e ** 2 / (4 * b) - f
        x_coeff = panbieshi / a
        y_coeff = panbieshi / b
        self.output.append(BaseValues([x_coeff, y_coeff]))
        return self


def _hyperbola_ab(x_coeff, y_coeff):
    if str(x_coeff) == "a**2" and str(y_coeff) == "-b**2":
        a = Symbol("a")
        b = Symbol("b")
    elif not y_coeff.free_symbols and y_coeff > 0:
        a = sqrt(y_coeff)
        b = sqrt(-x_coeff)
    elif x_coeff.free_symbols or x_coeff > 0:
        a = sqrt(x_coeff)
        b = sqrt(-y_coeff)
    else:
        a = sqrt(y_coeff)
        b = sqrt(-x_coeff)
    return a, b


# 求双曲线方程的a, b, c
class HyperbolaAbc(BaseFunction):
    def solver(self, *args):
        x_coeff, y_coeff = args[0].sympify()
        a, b = _hyperbola_ab(x_coeff, y_coeff)

        c = sqrt(a ** 2 + b ** 2)
        self.steps.append(
            ["", "双曲线的长半轴为%s, 短半轴为%s, 焦半径为%s" % (new_latex(a), new_latex(b), new_latex(c))])
        self.output.append(BaseValues([a, b, c]))
        self.label.add("求双曲线的a,b,c")
        return self


# 求双曲线的焦距
class HyperbolaJiaoJu(BaseFunction):
    def solver(self, *args):
        a, b, c = args[0].sympify()
        jiaoju = 2 * c
        self.steps.append(["", "∴双曲线的焦距为%s" % (new_latex(jiaoju))])
        self.output.append(BaseValue(jiaoju))
        self.label.add("求双曲线的焦距")
        return self


# 求双曲线的实轴
class HyperbolaRealAxis(BaseFunction):
    def solver(self, *args):
        a, b, c = args[0].sympify()
        shizhou = 2 * a
        self.steps.append(["", "∴双曲线的实轴为%s" % (new_latex(shizhou))])
        self.output.append(BaseValue(shizhou))
        self.label.add("求双曲线的实轴")
        return self


# 求双曲线的离心率
class HyperbolaEccentricity(BaseFunction):
    def solver(self, *args):
        a, b, c = args[0].sympify()
        e = c / a
        self.steps.append(["", "∴双曲线的离心率为%s" % (new_latex(e))])
        self.output.append(BasePoly(e))
        self.label.add("求双曲线的离心率")
        return self


# 求双曲线的焦点坐标
class HyperbolaFocusPoints(BaseFunction):
    def solver(self, *args):
        symmetry_point = args[0].sympify()
        x_coeff, y_coeff = args[1].sympify()
        text = args[2]
        flags = [0, 0, 0]  # flags[0] 左焦点  flags[1] 右焦点 flags[2] 焦点
        if text.find("左") >= 0 and text.find("焦点") >= 0:
            flags[0] = 1
        elif text.find("右") >= 0 and text.find("焦点") >= 0:
            flags[1] = 1
        else:
            flags[2] = 1

        if flags[0] == 1:
            a, b = _hyperbola_ab(x_coeff, y_coeff)
            c = sqrt(a ** 2 + b ** 2)
            left_point = [symmetry_point[0] - c, symmetry_point[1]]
            self.steps.append(
                ["", "∴双曲线的左焦点坐标为%s" % (BasePoint({"name": "", "value": left_point}).printing())])
            self.output.append(BasePoint({"name": "", "value": left_point}))
            self.label.add("求双曲线的左焦点")
        elif flags[1] == 1:
            a, b = _hyperbola_ab(x_coeff, y_coeff)
            c = sqrt(a ** 2 + b ** 2)
            right_point = [symmetry_point[0] + c, symmetry_point[1]]
            self.steps.append(
                ["", "∴双曲线的右焦点坐标为%s" % (BasePoint({"name": "", "value": right_point}).printing())])
            self.output.append(BasePoint({"name": "", "value": right_point}))
            self.label.add("求双曲线的右焦点")
        elif flags[2] == 1:
            if x_coeff.free_symbols or x_coeff > 0:
                a, b = _hyperbola_ab(x_coeff, y_coeff)
                c = sqrt(a ** 2 + b ** 2)
                left_point = [symmetry_point[0] - c, symmetry_point[1]]
                right_point = [symmetry_point[0] + c, symmetry_point[1]]
                self.steps.append(["", "∴双曲线的左右焦点坐标分别为%s" % (
                    BasePoints([{"name": "", "value": left_point},
                                {"name": "", "value": right_point}]).printing())])
                self.output.append(BasePoints([{"name": "", "value": left_point},
                                               {"name": "", "value": right_point}]))
            else:
                a, b = _hyperbola_ab(x_coeff, y_coeff)
                c = sqrt(a ** 2 + b ** 2)
                up_point = [symmetry_point[0], symmetry_point[1] + c]
                down_point = [symmetry_point[0], symmetry_point[1] - c]
                self.steps.append(["", "∴双曲线的上下焦点坐标分别为%s" % (
                    BasePoints([{"name": "", "value": up_point},
                                {"name": "", "value": down_point}]).printing())])
                self.output.append(BasePoints([{"name": "", "value": up_point},
                                               {"name": "", "value": down_point}]))
            self.label.add("求双曲线的焦点坐标")
        return self


# 求双曲线的顶点坐标
class HyperbolaPeakPoints(BaseFunction):
    def solver(self, *args):
        symmetry_point = args[0].sympify()
        x_coeff, y_coeff = args[1].sympify()
        if x_coeff > 0:
            real_point_left = [symmetry_point[0] - sqrt(x_coeff), symmetry_point[1]]
            real_point_right = [symmetry_point[0] + sqrt(x_coeff), symmetry_point[1]]
            image_point_up = [symmetry_point[0], symmetry_point[1] + sqrt(y_coeff)]
            image_point_down = [symmetry_point[0], symmetry_point[1] - sqrt(y_coeff)]
            self.steps.append(["", "双曲线的实轴顶点坐标分别为%s" % (BasePoints([{"name": "", "value": real_point_left}, {"name": "", "value": real_point_right}]).printing())])
            self.steps.append(["", "双曲线的虚轴顶点坐标分别为%s" % (BasePoints([{"name": "", "value": image_point_up}, {"name": "", "value": image_point_down}]).printing())])
            self.output.append(BasePoints([{"name": "", "value": real_point_left}, {"name": "", "value": real_point_right}, {"name": "", "value": image_point_up}, {"name": "", "value": image_point_down}]))
        else:
            real_point_up = [symmetry_point[0], symmetry_point[1] + sqrt(y_coeff)]
            real_point_down = [symmetry_point[0], symmetry_point[1] - sqrt(y_coeff)]
            image_point_left = [symmetry_point[0] - sqrt(x_coeff), symmetry_point[1]]
            image_point_right = [symmetry_point[0] + sqrt(x_coeff), symmetry_point[1]]
            self.steps.append(["", "双曲线的实轴顶点坐标分别为%s" % (BasePoints([{"name": "", "value": real_point_up}, {"name": "", "value": real_point_down}]).printing())])

            self.steps.append(["", "双曲线的虚轴顶点坐标分别为%s" % (BasePoints([{"name": "", "value": image_point_left}, {"name": "", "value": image_point_right}]).printing())])
            self.output.append(BasePoints([{"name": "", "value": real_point_up}, {"name": "", "value": real_point_down},
                                           {"name": "", "value": image_point_left},
                                           {"name": "", "value": image_point_right}]))
        self.label.add("求双曲线的顶点坐标")
        return self


# 求双曲线的准线方程
class HyperbolaDirectris(BaseFunction):
    def solver(self, *args):
        symmetry_point = args[0].sympify()
        x_coeff, y_coeff = args[1].sympify()
        if x_coeff.free_symbols or x_coeff > 0:
            a, b = _hyperbola_ab(x_coeff, y_coeff)
            c = sqrt(a ** 2 + b ** 2)
            eq_left = [x, symmetry_point[0] - a ** 2 / c]
            eq_right = [x, symmetry_point[0] + a ** 2 / c]
            if "左" in args[2]:
                obj = BaseZhiXian({"name": "", "value": eq_left})
                self.steps.append(["", "∴双曲线的一条准线为%s" % (obj.printing())])

            elif "右" in args[2]:
                obj = BaseZhiXian({"name": "", "value": eq_right})
                self.steps.append(["", "∴双曲线的一条准线为%s" % (obj.printing())])
            else:
                obj = BaseZhiXians([{"name": "", "value": eq_left},
                                    {"name": "", "value": eq_right}])
                self.steps.append(["", "∴双曲线的左右准线分别为%s" % (obj.printing())])
            self.output.append(obj)
        else:
            a = sqrt(y_coeff)
            b = sqrt(-x_coeff)
            c = sqrt(a ** 2 + b ** 2)
            eq_up = [y, symmetry_point[1] + a ** 2 / c]
            eq_down = [y, symmetry_point[1] - a ** 2 / c]
            self.steps.append(["", "∴双曲线的上下准线分别为%s" % (BaseZhiXians([{"name": "", "value": eq_up}, {"name": "", "value": eq_down}]).printing())])
            self.output.append(BaseZhiXians([{"name": "", "value": eq_up}, {"name": "", "value": eq_down}]))
        self.label.add("求双曲线的准线方程")
        return self


# 求双曲线的渐近线方程
class HyperbolaAsymptote(BaseFunction):
    def solver(self, *args):
        x_coeff, y_coeff = args[0].sympify()
        if x_coeff.free_symbols or x_coeff > 0:
            a, b = _hyperbola_ab(x_coeff, y_coeff)
            eq_left = [y, b * x / a]
            eq_right = [y, -b * x / a]

            if "左" in args[1]:
                obj = BaseZhiXian({"name": "", "value": eq_left})
                self.steps.append(["", "∴双曲线的一条渐进线为%s" % (obj.printing())])

            elif "右" in args[1]:
                obj = BaseZhiXian({"name": "", "value": eq_right})
                self.steps.append(["", "∴双曲线的一条渐进线为%s" % (obj.printing())])
            else:
                obj = BaseZhiXians([{"name": "", "value": eq_left},
                                    {"name": "", "value": eq_right}])
                self.steps.append(["", "∴双曲线的渐进线分别为%s" % (obj.printing())])
            self.output.append(obj)

            # self.steps.append(["","∴双曲线的渐进线方程为%s" %(BaseZhiXians([{"name":"", "value":[y, b*x/a]},
            #                                                         {"name":"","value":[y, -b*x/a]}]).printing())])
            # self.output.append(BaseZhiXians([{"name":"", "value":[y, b*x/a]}, {"name":"","value":[y, -b*x/a]}]))
        else:
            a = sqrt(y_coeff)
            b = sqrt(-x_coeff)
            self.steps.append(["", "∴双曲线的渐进线方程为%s" % (BaseZhiXians([{"name": "", "value": [y, a * x / b]}, {"name": "", "value": [y, -a * x / b]}]).printing())])
            self.output.append(
                BaseZhiXians([{"name": "", "value": [y, a * x / b]}, {"name": "", "value": [y, -a * x / b]}]))
        self.label.add("求双曲线的渐近线方程")
        return self


# 将抛物线化为标准型
class ParabolaNormalized(BaseFunction):
    def solver(self, *args):
        obj = args[0]
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        if b == 0:
            biaozhunshi_left = (x + d / (2 * a)) ** 2
            biaozhunshi_right = -e * (y + f / e - d ** 2 / (4 * a * e)) / a
        elif a == 0:
            biaozhunshi_left = (y + e / (2 * b)) ** 2
            biaozhunshi_right = -d * (x + f / d - e ** 2 / (4 * d * b)) / b
        else:
            raise Exception("to do")
        eq = [biaozhunshi_left, biaozhunshi_right]
        self.steps.append(["", "抛物线的标准方程为%s" % (BaseEq([biaozhunshi_left, biaozhunshi_right]).printing())])
        self.output.append(BasePaoWuXian({"name": obj.name, "value": eq}))

        self.label.add("求抛物线的标准方程")
        return self


# 求抛物线的顶点坐标
class ParabolaPeakPoint(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        if b == 0:
            point = [-d / (2 * a), -f / e + d ** 2 / (4 * a * e)]
        else:
            point = [-f / d + e ** 2 / (4 * d * b), -e / (2 * b)]
        self.steps.append(["", "∴抛物线的顶点坐标是%s" % (BasePoint({"name": "", "value": point}).printing())])
        self.output.append(BasePoint({"name": "", "value": point}))
        self.label.add("求抛物线的顶点坐标")
        return self


# 求抛物线的p值
class ParabolaPValue(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        if b == 0:
            p_value = Abs((-e / a) / 2)
        elif a == 0:
            p_value = Abs((-d / b) / 2)
        else:
            raise Exception("to do")
        self.steps.append(["", "∴%s" % (BaseEq([p, p_value]).printing())])
        self.output.append(BaseValue(p_value))
        self.label.add("求抛物线的p值")
        return self


# 求抛物线的焦点坐标
class ParabolaFocusPoint(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        peak_point = ParabolaPeakPoint().solver(args[0]).output[0].sympify()
        if b == 0:
            p_value = (-e / a) / 2
            focus_point = [peak_point[0], peak_point[1] + p_value / 2]
            self.steps.append(["", "∴抛物线的焦点坐标为%s" % (BasePoint({"name": "", "value": focus_point}).printing())])
            self.output.append(BasePoint({"name": "", "value": focus_point}))
        elif a == 0:
            p_value = (-d / b) / 2
            focus_point = [peak_point[0] + p_value / 2, peak_point[1]]
            self.steps.append(["", "∴抛物线的焦点坐标为%s" % (BasePoint({"name": "", "value": focus_point}).printing())])
            self.output.append(BasePoint({"name": "", "value": focus_point}))
        self.label.add("求抛物线的焦点坐标")
        return self


# 求抛物线的准线方程
class ParabolaDirectrix(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        peak_point = ParabolaPeakPoint().solver(args[0]).output[0].sympify()
        if b == 0:
            p_value = (-e / a) / 2
            directrix = [y, peak_point[1] - p_value / 2]
            self.steps.append(
                ["", "∴抛物线的准线方程为%s" % (BaseZhiXian({"name": "", "value": directrix}).printing())])
            self.output.append(BaseZhiXian({"name": "", "value": directrix}))
        elif a == 0:
            p_value = (-d / b) / 2
            directrix = [x, peak_point[1] - p_value / 2]
            self.steps.append(
                ["", "∴抛物线的准线方程为%s" % (BaseZhiXian({"name": "", "value": directrix}).printing())])
            self.output.append(BaseZhiXian({"name": "", "value": directrix}))
        self.label.add("求抛物线的准线")
        return self


# 求抛物线的对称轴
class ParabolaSymmetryAxis(BaseFunction):
    def solver(self, *args):
        a, b, c, d, e, f = ErYuanErCiCoeff().solver(args[0]).output[0].sympify()
        if b == 0:
            symmetry_axis = [x, -d / (2 * a)]
        elif a == 0:
            symmetry_axis = [y, -e / (2 * b)]
        else:
            raise Exception("to do")
        self.steps.append(["", "∴抛物线的对称轴为%s" % (BaseZhiXian({"name": "", "value": symmetry_axis}).printing())])
        self.output.append(BaseZhiXian({"name": "", "value": symmetry_axis}))
        self.label.add("求抛物线的对称轴方程")
        return self


if __name__ == '__main__':
    pass
